

#include "descriptor.h"

#include <sys/select.h>
#include <sys/time.h>

#include <cerrno>
#include <cassert>
#include <cstddef>// nullptr

namespace tty {
    namespace common {
        namespace sys {

bool get_descriptor_status(int fd, int sec, int nsec, e_rw desc, int ntimes)
{	
	assert(fd >= 0);
	assert(sec >= 0);
	assert(nsec >= 0);
	assert(ntimes >= 0);
	
	int fdmax = fd;
	fd_set read_fds;
	fd_set write_fds;
	
	FD_ZERO(&read_fds);
	FD_ZERO(&write_fds);
	
	if (desc == e_rw::read_write_fd) {
		FD_SET(fd, &read_fds);
		FD_SET(fd, &write_fds);
	}
	else if (desc == e_rw::read_fd) {
		FD_SET(fd, &read_fds);
	}
	else {
		FD_SET(fd, &write_fds);
	}	
	struct timespec timeout;
	timeout.tv_sec = sec;
	timeout.tv_nsec = nsec;
		
	for (int count = 0; count < ntimes; ++count) {		
		int ret = pselect(fdmax + 1, &read_fds, &write_fds, 0, &timeout, 0);
		if (ret < 0 && errno != EINTR) break;
		
		if (0 == ret) {				// timeout			
			FD_SET(fd, &read_fds);
			FD_SET(fd, &write_fds);
			continue;
		}		
		else if (errno == EINTR) break;		// Signal detected.		
		
		bool r = FD_ISSET(fd, &read_fds);
		bool w = FD_ISSET(fd, &write_fds);
		
		if (r && w && (desc == e_rw::read_write_fd))
			return true;
		else if (r && (desc == e_rw::read_fd))
			return true;
		else if (w && (desc == e_rw::write_fd))
			return true;			
	}			
	return false;
}


}}}  // namespace tty::common::sys
